package org.jing.core.lang.data;

import org.jing.core.lang.JingException;
import org.jing.core.lang.itf.JLoopTwo;
import org.jing.core.util.ClassUtil;

import java.io.Closeable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * Description: 常量Map. <br>
 * 一旦修改完参数后锁定就不能再修改了. <br>
 *
 * @author bks <br>
 * @since 2024-07-26 <br>
 */
@SuppressWarnings("unused")
public class ConstMap<K, V> implements JLoopTwo<K, V>, Closeable {
    private final Map<K, V> map;

    private boolean closed = false;

    /**
     * Description: 指定Map的实现类型. <br>
     *
     * @param type 实现类型 <br>
     */
    public ConstMap(Class<? extends Map<K, V>> type) {
        map = ClassUtil.createInstance(type);
    }

    /**
     * Description: 指定Map的实现类型为HashMap. <br>
     */
    public ConstMap() {
        map = new HashMap<>();
    }

    /**
     * Description: 指定Map的实现类型. <br>
     *
     * @param map 实现类 <br>
     */
    public ConstMap(Map<K, V> map) {
        this.map = map;
    }

    /**
     * Description: 设置一个键值对. <br>
     *
     * @param key 键 <br>
     * @param value 值 <br>
     * @return <u>链式调用</u> <br>
     */
    public ConstMap<K, V> put(K key, V value) {
        check();
        map.put(key, value);
        return this;
    }

    /**
     * Description: 移除一个键值对. <br>
     *
     * @param key 键 <br>
     * @return 移除的值 <br>
     */
    public V remove(K key) {
        check();
        return map.remove(key);
    }

    /**
     * Description: 清空Map. <br>
     *
     * @return <u>l链式调用</u> <br>
     */
    public ConstMap<K, V> clear() {
        check();
        map.clear();
        return this;
    }

    /**
     * Description: 覆盖Map. <br>
     *
     * @return <u>l链式调用</u> <br>
     */
    public ConstMap<K, V> putAll(Map<K, V> map) {
        check();
        this.map.putAll(map);
        return this;
    }

    /**
     * Description: 获取Map大小. <br>
     *
     * @return <br>
     */
    public int size() {
        return map.size();
    }

    /**
     * Description: 根据键获取值. <br>
     *
     * @return <br>
     */
    public V get(K key) {
        return map.get(key);
    }

    /**
     * Description: 判断Map是否有键. <br>
     *
     * @param key 键 <br>
     * @return <br>
     */
    public boolean containsKey(K key) {
        return map.containsKey(key);
    }

    /**
     * Description: 判断Map是否有值. <br>
     *
     * @param value 值 <br>
     * @return <br>
     */
    public boolean containsValue(V value) {
        return map.containsValue(value);
    }

    /**
     * Description: 遍历. <br>
     *
     * @param actions 方法 <br>
     */
    public void forEach(BiConsumer<K, V> actions) {
        map.forEach(actions);
    }

    /**
     * Description: 根据键获取值, 如果获取不到则使用默认值. <br>
     *
     * @param key 键 <br>
     * @param defaultValue 默认值 <br>
     * @return <br>
     */
    public V getOrDefault(K key, V defaultValue) {
        return map.getOrDefault(key, defaultValue);
    }

    private void check() {
        if (closed) throw new JingException("no update permit to closed map");
    }

    public ConstMap<K, V> lock() {
        closed = true;
        return this;
    }

    /**
     * Description: 锁定Map不再能更新. <br>
     */
    @Override public synchronized void close() {
        closed = true;
    }
}
